home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / incoming / libgr-2.000 / libgr-2 / libgr-2.0.3 / rle / dither.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-14  |  8.2 KB  |  289 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * dither.c - Functions for RGB color dithering.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    Mon Feb  2 1987
  28.  * Copyright (c) 1987, University of Utah
  29.  */
  30. static char rcsid[] = "/usr/local/src/CVS/libgr/rle/dither.c,v 1.1.1.1 1995/08/15 02:46:21 neal Exp";
  31.  
  32. #include <math.h>
  33.  
  34. #ifdef USE_PROTOTYPES
  35. void    make_square( double, int [256], int [256], int [16][16] );
  36. #else
  37. void    make_square();
  38. #endif
  39.  
  40. static int magic4x4[4][4] =  {
  41.       0, 14,  3, 13,
  42.     11,  5,  8,  6,
  43.     12,  2, 15,  1,
  44.      7,  9,  4, 10
  45. };
  46.  
  47. /* basic dithering macro */
  48. #define DMAP(v,x,y)    (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])
  49.  
  50.  
  51. /*****************************************************************
  52.  * TAG( dithermap )
  53.  * 
  54.  * Create a color dithering map with a specified number of intensity levels.
  55.  * Inputs:
  56.  *     levels:        Intensity levels per primary.
  57.  *    gamma:        Display gamma value.
  58.  * Outputs:
  59.  *     rgbmap:        Generated color map.
  60.  *    divN:        "div" function for dithering.
  61.  *    modN:        "mod" function for dithering.
  62.  * Assumptions:
  63.  *     rgbmap will hold levels^3 entries.
  64.  * Algorithm:
  65.  *    Compute gamma compensation map.
  66.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  67.  *    Compute rgbmap with red ramping fastest, green slower, and blue
  68.  *    slowest (treat it as if it were rgbmap[levels][levels][levels][3]).
  69.  *    Call make_square to get divN, modN, and magic
  70.  *
  71.  * Note:
  72.  *    Call dithergb( x, y, r, g, b, levels, divN, modN, magic ) to get index
  73.  *    into rgbmap for a given color/location pair, or use
  74.  *        row = y % 16; col = x % 16;
  75.  *        DMAP(v,col,row) =def (divN[v] + (modN[v]>magic[col][row] ? 1 : 0))
  76.  *        DMAP(r,col,row) + DMAP(g,col,row)*levels + DMAP(b,col,row)*levels^2
  77.  *    if you don't want function call overhead.
  78.  */
  79. void
  80. dithermap( levels, gamma, rgbmap, divN, modN, magic )
  81. int levels;
  82. double gamma;
  83. int rgbmap[][3];
  84. int divN[256];
  85. int modN[256];
  86. int magic[16][16];
  87. {
  88.     double N;
  89.     register int i;
  90.     int levelsq, levelsc;
  91.     int gammamap[256];
  92.     
  93.     for ( i = 0; i < 256; i++ )
  94.     gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  95.  
  96.     levelsq = levels*levels;    /* squared */
  97.     levelsc = levels*levelsq;    /* and cubed */
  98.  
  99.     N = 255.0 / (levels - 1);    /* Get size of each step */
  100.  
  101.     /* 
  102.      * Set up the color map entries.
  103.      */
  104.     for(i = 0; i < levelsc; i++) {
  105.     rgbmap[i][0] = gammamap[(int)(0.5 + (i%levels) * N)];
  106.     rgbmap[i][1] = gammamap[(int)(0.5 + ((i/levels)%levels) * N)];
  107.     rgbmap[i][2] = gammamap[(int)(0.5 + ((i/levelsq)%levels) * N)];
  108.     }
  109.  
  110.     make_square( N, divN, modN, magic );
  111. }
  112.  
  113.  
  114. /*****************************************************************
  115.  * TAG( bwdithermap )
  116.  * 
  117.  * Create a color dithering map with a specified number of intensity levels.
  118.  * Inputs:
  119.  *     levels:        Intensity levels.
  120.  *    gamma:        Display gamma value.
  121.  * Outputs:
  122.  *     bwmap:        Generated black & white map.
  123.  *    divN:        "div" function for dithering.
  124.  *    modN:        "mod" function for dithering.
  125.  * Assumptions:
  126.  *     bwmap will hold levels entries.
  127.  * Algorithm:
  128.  *    Compute gamma compensation map.
  129.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  130.  *    Compute bwmap for levels entries.
  131.  *    Call make_square to get divN, modN, and magic.
  132.  * Note:
  133.  *    Call ditherbw( x, y, val, divN, modN, magic ) to get index into 
  134.  *    bwmap for a given color/location pair, or use
  135.  *        row = y % 16; col = x % 16;
  136.  *        divN[val] + (modN[val]>magic[col][row] ? 1 : 0)
  137.  *    if you don't want function call overhead.
  138.  *    On a 1-bit display, use
  139.  *        divN[val] > magic[col][row] ? 1 : 0
  140.  */
  141. void
  142. bwdithermap( levels, gamma, bwmap, divN, modN, magic )
  143. int levels;
  144. double gamma;
  145. int bwmap[];
  146. int divN[256];
  147. int modN[256];
  148. int magic[16][16];
  149. {
  150.     double N;
  151.     register int i;
  152.     int gammamap[256];
  153.     
  154.     for ( i = 0; i < 256; i++ )
  155.     gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  156.  
  157.     N = 255.0 / (levels - 1);    /* Get size of each step */
  158.  
  159.     /* 
  160.      * Set up the color map entries.
  161.      */
  162.     for(i = 0; i < levels; i++)
  163.     bwmap[i] = gammamap[(int)(0.5 + i * N)];
  164.  
  165.     make_square( N, divN, modN, magic );
  166. }
  167.  
  168.  
  169. /*****************************************************************
  170.  * TAG( make_square )
  171.  * 
  172.  * Build the magic square for a given number of levels.
  173.  * Inputs:
  174.  *     N:        Pixel values per level (255.0 / levels).
  175.  * Outputs:
  176.  *     divN:        Integer value of pixval / N
  177.  *    modN:        Integer remainder between pixval and divN[pixval]*N
  178.  *    magic:        Magic square for dithering to N sublevels.
  179.  * Assumptions:
  180.  *     
  181.  * Algorithm:
  182.  *    divN[pixval] = (int)(pixval / N) maps pixval to its appropriate level.
  183.  *    modN[pixval] = pixval - (int)(N * divN[pixval]) maps pixval to
  184.  *    its sublevel, and is used in the dithering computation.
  185.  *    The magic square is computed as the (modified) outer product of
  186.  *    a 4x4 magic square with itself.
  187.  *    magic[4*k + i][4*l + j] = (magic4x4[i][j] + magic4x4[k][l]/16.0)
  188.  *    multiplied by an appropriate factor to get the correct dithering
  189.  *    range.
  190.  */
  191. void
  192. make_square( N, divN, modN, magic )
  193. double N;
  194. int divN[256];
  195. int modN[256];
  196. int magic[16][16] ;
  197. {
  198.     register int i, j, k, l;
  199.     double magicfact;
  200.  
  201.     for ( i = 0; i < 256; i++ )
  202.     {
  203.     divN[i] = (int)(i / N);
  204.     modN[i] = i - (int)(N * divN[i]);
  205.     }
  206.     modN[255] = 0;        /* always */
  207.  
  208.     /*
  209.      * Expand 4x4 dither pattern to 16x16.  4x4 leaves obvious patterning,
  210.      * and doesn't give us full intensity range (only 17 sublevels).
  211.      * 
  212.      * magicfact is (N - 1)/16 so that we get numbers in the matrix from 0 to
  213.      * N - 1: mod N gives numbers in 0 to N - 1, don't ever want all
  214.      * pixels incremented to the next level (this is reserved for the
  215.      * pixel value with mod N == 0 at the next level).
  216.      */
  217.     magicfact = (N - 1) / 16.;
  218.     for ( i = 0; i < 4; i++ )
  219.     for ( j = 0; j < 4; j++ )
  220.         for ( k = 0; k < 4; k++ )
  221.         for ( l = 0; l < 4; l++ )
  222.             magic[4*k+i][4*l+j] =
  223.             (int)(0.5 + magic4x4[i][j] * magicfact +
  224.                   (magic4x4[k][l] / 16.) * magicfact);
  225. }
  226.  
  227.  
  228. /*****************************************************************
  229.  * TAG( dithergb )
  230.  * 
  231.  * Return dithered RGB value.
  232.  * Inputs:
  233.  *     x:        X location on screen of this pixel.
  234.  *    y:        Y location on screen of this pixel.
  235.  *    r, g, b:    Color at this pixel (0 - 255 range).
  236.  *    levels:        Number of levels in this map.
  237.  *    divN, modN:    From dithermap.
  238.  *    magic:        Magic square from dithermap.
  239.  * Outputs:
  240.  *     Returns color map index for dithered pixelv value.
  241.  * Assumptions:
  242.  *     divN, modN, magic were set up properly.
  243.  * Algorithm:
  244.  *     see "Note:" in dithermap comment.
  245.  */
  246. int
  247. dithergb( x, y, r, g, b, levels, divN, modN, magic )
  248. int x, y, r, g, b, levels;
  249. int divN[256];
  250. int modN[256];
  251. int magic[16][16];
  252. {
  253.     int col = x % 16, row = y % 16;
  254.  
  255.     return DMAP(r, col, row) +
  256.     DMAP(g, col, row) * levels +
  257.         DMAP(b, col, row) * levels*levels;
  258. }
  259.  
  260.  
  261. /*****************************************************************
  262.  * TAG( ditherbw )
  263.  * 
  264.  * Return dithered black & white value.
  265.  * Inputs:
  266.  *     x:        X location on screen of this pixel.
  267.  *    y:        Y location on screen of this pixel.
  268.  *    val:        Intensity at this pixel (0 - 255 range).
  269.  *    divN, modN:    From dithermap.
  270.  *    magic:        Magic square from dithermap.
  271.  * Outputs:
  272.  *     Returns color map index for dithered pixel value.
  273.  * Assumptions:
  274.  *     divN, modN, magic were set up properly.
  275.  * Algorithm:
  276.  *     see "Note:" in bwdithermap comment.
  277.  */
  278. int
  279. ditherbw( x, y, val, divN, modN, magic )
  280. int x, y, val;
  281. int divN[256];
  282. int modN[256];
  283. int magic[16][16];
  284. {
  285.     int col = x % 16, row = y % 16;
  286.  
  287.     return DMAP(val, col, row);
  288. }
  289.